package com.gitee.denger.mybatis.example.ext.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;

/**
 * class 工具类
 *
 * @author 登琼
 */
public abstract class ClassUtils {
    /**
     * 获取实现接口的泛型参数
     *
     * @param objClazz       对象的class
     * @param interfaceClazz 获取该接口的泛型
     * @return 可能为null
     */
    public static Type[] getGenericInterfaceActualTypeArguments(Class<?> objClazz, Class<?> interfaceClazz) {
        Type[] actualTypeArguments = null;
        for (Type param : objClazz.getGenericInterfaces()) {
            if (param.getTypeName().startsWith(interfaceClazz.getTypeName())) {
                if (param instanceof ParameterizedType) {
                    actualTypeArguments = ((ParameterizedType) param).getActualTypeArguments();
                }
                break;
            }
        }
        return actualTypeArguments;
    }

    /**
     * 获取实例对象
     *
     * @param clazz class
     * @param <T>   泛型对象
     * @return 对象实例
     */
    public static <T> T newInstance(Class<T> clazz) {
        try {
            return clazz.newInstance();
        } catch (Exception e) {
            String msg = "实例化泛型出现异常:" + clazz;
            throw new IllegalArgumentException(msg, e);
        }
    }

    /**
     * 根据构造函数获取实例对象
     *
     * @param clazz    class
     * @param initargs 参数
     * @param <T>      泛型对象
     * @return 对象实例
     */
    public static <T> T newInstance(Class<T> clazz, Object... initargs) {
        Class<?>[] parameterTypes = new Class<?>[initargs.length];
        for (int i = 0; i < initargs.length; i++) {
            parameterTypes[i] = initargs[i].getClass();
        }
        try {
            Constructor<T> constructor = clazz.getConstructor(parameterTypes);
            return constructor.newInstance(initargs);
        } catch (Exception e) {
            String msg = "根据构造函数实例泛型出现异常:" + clazz + " ;参数类型为" + Arrays.toString(parameterTypes);
            throw new IllegalArgumentException(msg, e);
        }
    }
}
